/*
 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
 * Licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PSL v2. You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
 * Mulan PSL v2 for more details.
 */

#include "adaptor_log.h"
#include "pin_auth.h"
#include "pin_db.h"
#include "pin_func.h"
#include "tee_defines.h"
#include <securec.h>
#include <stdint.h>
#include <tee_core_api.h>
#include <tee_ext_api.h>
#include <tee_log.h>
#include <tee_mem_mgmt_api.h>
#include <tee_trusted_storage_api.h>

#define PARAM_COUNT 4

enum {
  CMD_ENROLL_PIN = 1,
  CMD_AUTH_PIN,
  CMD_WRITE_ANTI_BRUTE,
  CMD_QUERY_PIN_INFO,
  CMD_DELETE_TEMPLATE,
  CMD_GET_EXECUTOR_INFO,
  CMD_VERIFY_TEMPLATE_DATA,
  CMD_GENERATE_ALGO_PARAMETER,
  CMD_GET_ALGO_PARAMETER,
};

const char *CMD_NAMES[] = {
    "NULL",
    "CMD_ENROLL_PIN",
    "CMD_AUTH_PIN",
    "CMD_WRITE_ANTI_BRUTE",
    "CMD_QUERY_PIN_INFO",
    "CMD_DELETE_TEMPLATE",
    "CMD_GET_EXECUTOR_INFO",
    "CMD_VERIFY_TEMPLATE_DATA",
    "CMD_GENERATE_ALGO_PARAMETER",
    "CMD_GET_ALGO_PARAMETER",
};

static TEE_Result tee_init() {
  if (!LoadPinDb()) {
    LOG_ERROR("LoadPinDb fail!");
    return TEE_ERROR_GENERIC;
  }
  LOG_INFO("LoadPinDb success!");
  if (GenerateKeyPair() != RESULT_SUCCESS) {
    LOG_ERROR("GenerateKeyPair fail!");
    return TEE_ERROR_GENERIC;
  }
  LOG_INFO("GenerateKeyPair success!");

  return TEE_SUCCESS;
}

TEE_Result TA_CreateEntryPoint(void) {
  LOG_INFO("----- TA entry point ----- ");
  return TEE_SUCCESS;
}

TEE_Result TA_OpenSessionEntryPoint(uint32_t param_type,
                                    TEE_Param params[PARAM_COUNT],
                                    void **session_context) {
  (void)param_type;
  (void)params;
  (void)session_context;
  LOG_INFO("---- TA open session -------- ");

  return tee_init();
}

TEE_Result TA_InvokeCommandEntryPoint(void *session_context, uint32_t cmd,
                                      uint32_t param_type,
                                      TEE_Param params[PARAM_COUNT]) {
  TEE_Result ret;
  (void)session_context;

  LOG_INFO("---- TA invoke command ----------- ");
  LOG_INFO("==========cmd is %s==========", CMD_NAMES[cmd]);
  switch (cmd) {
  case CMD_ENROLL_PIN:
    ret = EnrollPin(param_type, params);
    break;
  case CMD_GET_EXECUTOR_INFO:
    ret = GetExecutorInfo(param_type, params);
    break;
  case CMD_VERIFY_TEMPLATE_DATA:
    ret = VerifyTemplateData(param_type, params);
    break;
  case CMD_QUERY_PIN_INFO:
    ret = QueryPinInfo(param_type, params);
    break;
  case CMD_AUTH_PIN:
    ret = AuthPin(param_type, params);
    break;
  case CMD_WRITE_ANTI_BRUTE:
    ret = WriteAntiBrute(param_type, params);
    break;
  case CMD_DELETE_TEMPLATE:
    ret = DeleteTemplate(param_type, params);
    break;
  case CMD_GENERATE_ALGO_PARAMETER:
    ret = GenerateAlgoParameter(param_type, params);
    break;
  case CMD_GET_ALGO_PARAMETER:
    ret = GetAlgoParameter(param_type, params);
    break;
  default:
    LOG_ERROR("Unknown cmd is %u", cmd);
    ret = TEE_ERROR_BAD_PARAMETERS;
  }

  return ret;
}

void TA_CloseSessionEntryPoint(void *session_context) {
  (void)session_context;
  LOG_INFO("---- close session ----- ");
}

void TA_DestroyEntryPoint(void) { LOG_INFO("---- destroy TA ---- "); }
